/*
 * StreamBuffer.cpp
 *
 *  Created on: Mar 27, 2013
 *      Author: root
 */

#include "StreamBuffer.h"

StreamBuffer::StreamBuffer()
{
	current_packet_count = 0;
	total_count = 0;
	buf = NULL;
}

StreamBuffer::~StreamBuffer()
{
	while(this->free_pkt_pool.size() > 0)
	{
		/*free pkt*/
		AVPacket * pkt = this->free_pkt_pool.top();
		this->free_pkt_pool.pop();

		delete pkt;
		pkt = NULL;
	}
	/*free buf*/
	if(buf != _NULL)
	{
		delete [] buf;
	}
}

int StreamBuffer::init(uint16_t max_stream_num,uint16_t max_stream_pkt_count)
{
	if(max_stream_num == 0)
		return FAILURE;

	int init_packet_count = max_stream_num * max_stream_pkt_count;
	/*init alloc large buf*/
	buf  = new ubyte[AV_CHUNK_SIZE * init_packet_count];
	if(buf == _NULL)
		return FAILURE;
	else
		memset(buf,'\0',AV_CHUNK_SIZE * init_packet_count);

	buf_lock.Lock();
	{
		/*split buf to all packets*/
		ubyte * pbuf = buf;
		for(int i = 0;i < init_packet_count;i++)
		{
			AVPacket *newpkt = new AVPacket();
			if(newpkt == _NULL)
			{
				buf_lock.Unlock();
				return FAILURE;
			}
			newpkt->data = pbuf;
			newpkt->data_size = AV_CHUNK_SIZE;
			pbuf += AV_CHUNK_SIZE;
			free_pkt_pool.push(newpkt);
			total_count ++;
		}

		buf_lock.Unlock();
	}

	return SUCCESS;

}

/*
*alloc packet
*/
int StreamBuffer::alloc_pkt(AVPacket **ptk)
{
	buf_lock.Lock();
	{
		if(free_pkt_pool.size()>0)
		{
			(*ptk) = free_pkt_pool.top();
			free_pkt_pool.pop();
			current_packet_count++;
		}
		else
		{
			AVPacket *newpkt = new AVPacket();
			if(newpkt == _NULL)
			{
				buf_lock.Unlock();
				return FAILURE;
			}
			newpkt->data = new ubyte[AV_CHUNK_SIZE];
			if(newpkt->data == _NULL)
			{
				delete newpkt;
				newpkt = NULL;
				buf_lock.Unlock();
				return FAILURE;
			}
			newpkt->data_size = AV_CHUNK_SIZE;
			(*ptk) = newpkt;
			current_packet_count++;
			total_count ++;
		}
		buf_lock.Unlock();
	}
	return SUCCESS;
}

/*
*free packet to memory pool
*/
int StreamBuffer::free_pkt(AVPacket *pkt)
{
	buf_lock.Lock();
	{
		if(pkt != NULL)
		{
			pkt->chunck_size = 0;
			pkt->chunck_offset = 0;
			pkt->data_len = 0;
			pkt->pkt_index = 0;
			pkt->next = NULL;
			pkt->prev = NULL;
			pkt->stream_id = 0;
			pkt->last_frame_offset = 0;
			pkt->last_frame_size = 0;
			pkt->last_key_frame_offset = 0;
			pkt->pts = 0;
			pkt->dts = 0;
			free_pkt_pool.push(pkt);
			current_packet_count --;
		}
		else
		{
			buf_lock.Unlock();
			return FAILURE;
		}
		buf_lock.Unlock();
	}
	return SUCCESS;
}

/*
*free n packets to memory pool,but pkt header
*/
int StreamBuffer::free_pkt(AVPacket *hpkt,int count)
{
	AVPacket *pkt = hpkt->next;
	int c = count;

	while(pkt != NULL && c>0)
	{
		hpkt->next = pkt->next;
		if(pkt->next!=NULL)
			 pkt->next->prev = hpkt;

		free_pkt(pkt);
		pkt = hpkt->next;
		c--;
	}
	return SUCCESS;
}

int StreamBuffer::get_current_packet_count(void)
{
	return current_packet_count;
}

int StreamBuffer::get_free_packet_count(void)
{
	return (int)(free_pkt_pool.size());
}

int StreamBuffer::get_total_count(void)
{
	return total_count;
}

